package src;

import jargs.gnu.CmdLineParser;
import jargs.gnu.CmdLineParser.IllegalOptionValueException;
import jargs.gnu.CmdLineParser.UnknownOptionException;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import lib.Utility;
import lib.messaging.NetworkAddress;

public class ServerConfiguration
{
    private static final String JoinArgLongName = "join";
    private static final char JoinArgShortName = 'j';
    private static final String PacketDropProbabilityArgLongName = "dropPacketProbability";
    private static final char PacketDropProbabilityArgShortName = 'd';
    private static final String ReconfigureArgLongName = "reconfig";
    private static final char ReconfigureArgShortName = 'r';
    private static final String PortArgLongName = "port";
    private static final char PortArgShortName = 'p';
    public static String ServerName = "localhost";
    public static final File ServerRootDirectory = Utility.GetCurrentWorkingDirectory();
    public static final int Timeout = 3000;
    public static final String AcceptorStateDumpFileNameFormatString = "AcceptorStateDump_%s_%d.txt";

    public static ServerConfiguration ReadConfiguration(String[] args)
            throws IllegalOptionValueException, UnknownOptionException
    {

        CmdLineParser parser = new CmdLineParser();
        CmdLineParser.Option portOption = parser.addStringOption(PortArgShortName, PortArgLongName);
        CmdLineParser.Option packetDropProbabilityOption = parser.addStringOption(
                PacketDropProbabilityArgShortName,
                PacketDropProbabilityArgLongName);
        CmdLineParser.Option joinServer = parser.addStringOption(
                JoinArgShortName,
                JoinArgLongName);
        CmdLineParser.Option reconfigureOption = parser.addStringOption(
                ReconfigureArgShortName,
                ReconfigureArgLongName);

        parser.parse(args);

        String port = (String) parser.getOptionValue(portOption);
        NetworkAddress serverAddress = new NetworkAddress(ServerName, Integer.parseInt(port));

        String packetDropProbability = (String) parser.getOptionValue(packetDropProbabilityOption);

        boolean reconfigure = Boolean.parseBoolean((String) parser.getOptionValue(reconfigureOption));

        List<NetworkAddress> otherServerAddresses = new ArrayList<NetworkAddress>();
        NetworkAddress existingServerAddress = null;
        String existingServer = (String) parser.getOptionValue(joinServer);

        boolean joinExistingServer = false;
        if (existingServer != null)
        {
            existingServerAddress = new NetworkAddress(ServerName, Integer.parseInt(existingServer));
            otherServerAddresses.add(existingServerAddress);
            joinExistingServer = true;
        }
        else
        {
            String[] otherServers = parser.getRemainingArgs();

            for (int i = 0; i < otherServers.length; ++i)
            {
                otherServerAddresses.add(new NetworkAddress(ServerName, Integer.parseInt(otherServers[i])));
            }

            existingServerAddress = otherServerAddresses.get(0);
        }

        ServerConfiguration config = new ServerConfiguration();
        config.serverAddress = serverAddress;
        config.serverPacketDropProbability = Double.parseDouble(packetDropProbability);
        config.otherServerAddresses = otherServerAddresses;
        config.joinExistingServer = joinExistingServer;
        config.existingServerAddress = existingServerAddress;
        config.reconfigureAutomatically = reconfigure;
        return config;
    }

    private NetworkAddress existingServerAddress;
    private boolean joinExistingServer;
    private boolean reconfigureAutomatically;
    private List<NetworkAddress> otherServerAddresses;
    private NetworkAddress serverAddress;
    private double serverPacketDropProbability;

    public NetworkAddress ExistingServerAddress()
    {
        return existingServerAddress;
    }

    public boolean JoinExistingServer()
    {
        return joinExistingServer;
    }

    public List<NetworkAddress> OtherServerAddresses()
    {
        return otherServerAddresses;
    }

    public boolean ReconfigureAutomatically()
    {
        return reconfigureAutomatically;
    }

    public NetworkAddress ServerAddress()
    {
        return serverAddress;
    }

    public double ServerPacketDropProbability()
    {
        return serverPacketDropProbability;
    }
}
